package com.psedu.base.service.impl;
import java.io.File;
import java.util.Date;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.psedu.base.api.domain.dto.StudentDTO;
import com.psedu.base.constant.Constants;
import com.psedu.base.domain.Apply;
import com.psedu.base.domain.Semester;
import com.psedu.base.domain.vo.CertificateStudentVo;
import com.psedu.base.domain.vo.StudentTrainDataVo;
import com.psedu.base.mapper.ApplyMapper;
import com.psedu.base.mapper.SemesterMapper;
import com.psedu.base.service.StudentService;
import com.psedu.base.utils.GraduateExcel;
import com.psedu.base.utils.HttpUtils;
import com.psedu.exam.api.RemoteExamService;
import com.psedu.exam.api.domain.vo.ExamBo;
import com.psedu.common.core.constant.HttpStatus;
import com.psedu.common.core.constant.SecurityConstants;
import com.psedu.common.core.domain.R;
import com.psedu.common.core.exception.ServiceException;
import com.psedu.common.security.utils.SecurityUtils;
import com.psedu.system.api.RemoteDeptService;
import com.psedu.system.api.RemoteUserService;
import com.psedu.system.api.model.LoginUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.psedu.common.core.utils.PageUtils.startPage;


/**
 * @author Mingyue
 * 报名审核通过后成为“学员”
 */
@Slf4j
@Service
public class StudentServiceImpl implements StudentService {

    @Autowired
    private ApplyMapper applyMapper;

    @Autowired
    private RemoteExamService remoteExamService;
    
    @Autowired
    private RemoteDeptService remoteDeptService;

    @Autowired
    private SemesterMapper semesterMapper;

    @Autowired
    private RemoteUserService remoteUserService;

    @Override
    public List<ExamBo> getStudentExamList() {
        // 用戶信息
        String hnusterId = SecurityUtils.getUsername();
        LoginUser loginUser = SecurityUtils.getLoginUser();
        Long deptId = loginUser.getDeptId();
        List<Apply> applyList = applyMapper.selectList(
                new LambdaQueryWrapper<Apply>()
                        .eq(Apply::getHnusterId, hnusterId)
                        .eq(Apply::getChecked, Constants.APPLY_PASS)
        );
        List<Long> passSemeIds = applyList.stream().map(Apply::getSemeId).collect(Collectors.toList());
        if(CollectionUtil.isEmpty(passSemeIds)) {
            return CollectionUtil.empty(ExamBo.class);
        }
        // todo 要调用exam获取学期的所有考试列表，这也太慢了吧
        R<List<ExamBo>> examsR = remoteExamService.getExamsBySemeIdsAndDeptId(
                deptId, passSemeIds, SecurityConstants.INNER
        );
        List<ExamBo> examBos = examsR.getData();
        return examBos;
    }

    @Override
    public StudentDTO getStudentInfo(Long semesterId, Long psUserId) {
        StudentDTO studentDTO = new StudentDTO();
        Apply apply = applyMapper.selectOne(
                new LambdaQueryWrapper<Apply>()
                        .eq(Apply::getPsUserId, psUserId)
                        .eq(Apply::getSemeId, semesterId)
        );
        studentDTO.setApplyId(apply.getApplyId());
        studentDTO.setSemesterId(apply.getSemeId());
        studentDTO.setHnusterId(apply.getHnusterId());
        studentDTO.setStudentName(apply.getRealName());
        studentDTO.setScores(apply.getScores());
        return studentDTO;
    }

    @Override
    public int updateExamStudentScore(Long applyId, BigDecimal score) {
        Apply apply = new Apply();
        apply.setApplyId(applyId);
        apply.setScores(score);
        return applyMapper.updateById(apply);
    }

    @Override
    public List<Long> getAllPassSemester(Long psUserId) {
        List<Apply> applies = applyMapper.selectList(
                new LambdaQueryWrapper<Apply>()
                        .eq(Apply::getPsUserId, psUserId)
                        .eq(Apply::getChecked, Constants.APPLY_PASS)
        );
        return applies.stream().map(Apply::getSemeId).collect(Collectors.toList());
    }

    @Override
    public List<StudentTrainDataVo> getTrainDataList(Apply apply) {
        startPage();
        List<StudentTrainDataVo> studentTrainDataVos = applyMapper.selectTrainDataList(apply);
        fillDeptName(studentTrainDataVos);
        return studentTrainDataVos;
    }

    @Override
    public void downloadCertificate(Long semeId, Long deptId, HttpServletResponse httpResponse) {
        List<Apply> passStudentList = applyMapper.selectList(
                new LambdaQueryWrapper<Apply>()
                        .eq(Apply::getChecked, Constants.APPLY_PASS)
                        .ge(Apply::getScores, Constants.PASS_SCORE)
                        .eq(Apply::getSemeId, semeId)
                        .eq(Apply::getDeptId, deptId)
        );
        List<Long> userIdList = passStudentList.stream().map(Apply::getPsUserId).collect(Collectors.toList());
        if(userIdList.size() == 0) {
            throw new ServiceException("无结业证书下载", HttpStatus.NOT_FOUND);
        }
        R<Map<Long, String>> userProfileUrlMapR = remoteUserService.getUserProfile(userIdList, SecurityConstants.INNER);
        Map<Long, String> userProfileUrlMap = userProfileUrlMapR.getData();
        Map<Long, String> localUserProfileUrlMap = new HashMap<>();
        // 所有图片下载到本地
        for (Map.Entry<Long, String> userProfileEntity : userProfileUrlMap.entrySet()) {
            Long userId = userProfileEntity.getKey();
            String url = userProfileEntity.getValue();
            String fileName = url.substring(url.lastIndexOf("/"));
            String filePath =  File.separator + "projectFile" + File.separator +fileName;
            String localFilePath = "";
            try {
                localFilePath = HttpUtils.getFile(url, filePath);
                localUserProfileUrlMap.put(userId, localFilePath);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        // 本地图片路径存入 student 中
        List<CertificateStudentVo> certificateStudentVos = convertStudent2CertificateStudent(semeId, passStudentList);

        for (CertificateStudentVo certificateStudentVo : certificateStudentVos) {
            Long userId = certificateStudentVo.getUserId();
            String profilePath = localUserProfileUrlMap.getOrDefault(userId, "");
            certificateStudentVo.setProfile(profilePath);
        }
        System.out.println("certificateStudent");
        System.out.println(JSONObject.toJSONString(certificateStudentVos));
        GraduateExcel graduateExcel = new GraduateExcel(certificateStudentVos);
        System.out.println("graduateExcel" +graduateExcel.toString());
        HSSFWorkbook resWorkbook = graduateExcel.getResWorkbook();
        // test
//        HSSFWorkbook resWorkbook = null;
//        try {
//            graduateExcel.downloadExcel2Local();
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
        System.out.println("resWorkbook" +resWorkbook.toString());
        String sheetName = resWorkbook.getSheetName(0);
        outExcelStream(httpResponse, resWorkbook, sheetName);
    }

    @Override
    public StudentTrainDataVo studentTrainData(Long applyId) {
        StudentTrainDataVo studentTrainData = applyMapper.getStudentTrainData(applyId);
        return studentTrainData;
    }

    private List<CertificateStudentVo>  convertStudent2CertificateStudent(Long semeId, List<Apply> passStudentList) {
        R<Map<Long, String>> allDeptNameMapR = remoteDeptService.getAllDeptNameMap(SecurityConstants.INNER);
        Map<Long, String> allDeptNameMap = allDeptNameMapR.getData();
        List<CertificateStudentVo> certificateStudentList = passStudentList.stream().map(student -> {
            CertificateStudentVo certificateStudentVo = new CertificateStudentVo();
            certificateStudentVo.setUserId(student.getPsUserId());
            certificateStudentVo.setStudentName(student.getRealName());
            certificateStudentVo.setSex(student.getSex());
            certificateStudentVo.setBirthday(student.getBirthday());
            String unitName = allDeptNameMap.getOrDefault(student.getDeptId(), "")
                    + student.getClasses();
            certificateStudentVo.setUnit(unitName);
            // 学期数据
            Semester semester = semesterMapper.selectById(semeId);
            certificateStudentVo.setTrainStartDate(semester.getStartTime());
            certificateStudentVo.setTrainEndDate(semester.getEndTime());
            certificateStudentVo.setScore(student.getScores());
            String trainObjStr = "";
            switch (semester.getTrainObject()) {
                case Constants.TRAIN_OBJECT_ACT:
                    trainObjStr = "入党积极分子";
                    break;
                case Constants.TRAIN_OBJECT_DEV:
                    trainObjStr = "发展对象";
                    break;
                case Constants.TRAIN_OBJECT_PRE:
                    trainObjStr = "预备党员";
                    break;
            }
            certificateStudentVo.setComment("    该同志参加" + trainObjStr + "培训班学习，考核（考试）合格，准予结业。");
            certificateStudentVo.setIssueOrganization("中共湖南科技大学委员会党校");
            certificateStudentVo.setIssueDate(new Date());
            certificateStudentVo.setProfile("D:\\code\\school-project\\file\\profile.png");
            return certificateStudentVo;
        }).collect(Collectors.toList());
        return certificateStudentList;
    }

    /**
     * 通过流的方式输出excle到页面
     * @param response 响应
     * @param workbook 工作空间
     * @param fileName 文件名
     */
    public void outExcelStream(HttpServletResponse response, Workbook workbook, String fileName){
        OutputStream os = null;
        try {
            os = response.getOutputStream();
            response.setContentType("application/x-download");
            response.setCharacterEncoding("UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + new String(fileName.getBytes(), "ISO8859-1") + ".xls");
            workbook.write(os);
            os.flush();
        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(os!=null){
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void fillDeptName(List<StudentTrainDataVo> studentTrainDataVos) {
        R<Map<Long, String>> allDeptNameMapR = remoteDeptService.getAllDeptNameMap(SecurityConstants.INNER);
        Map<Long, String> allDeptNameMap = allDeptNameMapR.getData();
        for (StudentTrainDataVo studentTrainDataVo : studentTrainDataVos) {
            Long deptId = studentTrainDataVo.getDeptId();
            studentTrainDataVo.setDeptName(allDeptNameMap.getOrDefault(deptId, "部门不明"));
        }
    }
}
